﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using UtilsLib.UtilsConfiguration;
using UtilsLib.UtilsLog;

namespace UtilsLib.UtilsFile
{
    public static class FileLib
    {
        
        /// <summary>
        /// Init the LogToFile, Create the file, directory,...
        /// </summary>
        /// <param name="filePath">The path of the file (without the name)</param>
        /// <param name="fileName">The name of the file (without the path)</param>
        /// <param name="extension">The extension of the file</param>
        /// <param name="deleteOldFile">Specify if you want to delete the existing file if present</param>
        public static string CreateFile(string filePath, string fileName, string extension, bool deleteOldFile)
        {

            string _fileName = GetFileName(fileName, extension);
            string _directory = GetDirectory(filePath);

            string _path = AppDomain.CurrentDomain.BaseDirectory;
            string _pathToDir = _path + _directory;
            string _pathToFile = _pathToDir + "\\" + _fileName;


            CheckDirectory(_pathToDir);

            CheckFile(_pathToFile, deleteOldFile);

            return _pathToFile;
        }

        /// <summary>
        /// Get the Name of the file
        /// </summary>
        /// <param name="fileName">The core name of the file</param>
        /// <param name="extension">The extension of the file</param>
        /// <returns>The full name of the file</returns>
        public static string GetFileName(string fileName, string extension)
        {
            return (DateTime.Now.Day < 10 ? "0" + DateTime.Now.Day.ToString() : DateTime.Now.Day.ToString()) + "_" + fileName + "." + extension;
        }

        /// <summary>
        /// Get the directory path, from the app location
        /// </summary>
        /// <param name="filePath">The directory tree starting in the app location</param>
        /// <returns>The full directory tree to the file</returns>
        public static string GetDirectory(string filePath)
        {
            return filePath + "\\" + DateTime.Now.Year.ToString() + "\\" + (DateTime.Now.Month < 10 ? "0" + DateTime.Now.Month.ToString() : DateTime.Now.Month.ToString());
        }

        /// <summary>
        /// Get the Full Path of the file
        /// </summary>
        /// <param name="directoryPath">The directory path starting in the app location</param>
        /// <param name="fileName">The core name of the file</param>
        /// <param name="extension">The extension of the file</param>
        /// <returns>The full path of the file</returns>
        public static string GetPath(string directoryPath, string fileName, string extension)
        {
            string dirPathFull = GetDirectory(directoryPath);
            CheckDirectory(dirPathFull);
            return AppDomain.CurrentDomain.BaseDirectory + dirPathFull + "\\" + GetFileName(fileName, extension);
        }

        /// <summary>
        /// Get the relative path of the file
        /// </summary>
        /// <param name="directoryPath">The directory path starting in the app location</param>
        /// <param name="fileName">The core name of the file</param>
        /// <param name="extension">The extension of the file</param>
        /// <returns>The relative path of the file (starting in the app location) </returns>
        public static string GetRelativePath(string directoryPath, string fileName, string extension)
        {
            CheckDirectory(directoryPath);
            return GetDirectory(directoryPath) + "\\" + GetFileName(fileName, extension);
        }

        /// <summary>
        /// Create the directory if it does not exists
        /// </summary>
        /// <param name="dirPath">The directory to check</param>
        public static void CheckDirectory(string dirPath)
        {
            if (!Directory.Exists(dirPath))
                Directory.CreateDirectory(dirPath);
        }

        /// <summary>
        /// Create the file if it does not exists or delete and create or does nothing
        /// </summary>
        /// <param name="filePath">The full path to the file to check</param>
        /// <param name="deleteOldFile">Specify if you want to delete the existing file</param>
        public static void CheckFile(string filePath, bool deleteOldFile)
        {
            if (File.Exists(filePath) && deleteOldFile)
                try
                {
                    File.Delete(filePath);
                }
                catch (Exception ex)
                {
                    LogToFile.WriteException(ex, "Error deleting the old file.");
                    throw ex;
                }

            File.OpenWrite(filePath).Close();
        }

        /// <summary>
        /// Copy/Cut the full content of a directory
        /// </summary>
        /// <param name="dir">DirectoryInfo to Cut.</param>
        /// <param name="newPath">Path where to paste the directory</param>
        public static void DirectoryCutPasteTo(DirectoryInfo dir, string newPath)
        {
            UserImpersonation impersonator = new UserImpersonation();
            impersonator.ImpersonateUser(ConfigManager.AppSettings("username"), ConfigManager.AppSettings("domain"), ConfigManager.AppSettings("pass")); //Domain is optionnal
            DirectoryInfo dirCopyTo = new DirectoryInfo(newPath + "\\" + dir.Name);
            if (!dirCopyTo.Exists)
                dirCopyTo.Create();
            try
            {
                if (dir.GetFiles().Count() > 0)
                    foreach (FileInfo file in dir.GetFiles())
                    {
                        File.Copy(file.FullName, Path.Combine(@dirCopyTo.FullName + "\\" + file.Name), true);
                        file.Delete();
                    }

                bool copyOk = false;
                int time = 0;
                Thread.Sleep(5000); //attente d'éventuelle fin de copie
                while (!copyOk)
                    try
                    {
                        Console.WriteLine("Tentative de suppression");
                        dir.Delete(true);
                        copyOk = true;
                        Console.WriteLine("Suppression OK");
                    }
                    catch (Exception e)
                    {
                        Thread.Sleep(1000);
                        Console.WriteLine("Attente de suppression");
                        time++;
                        if (!copyOk && time > 15)
                        {
                            LogToFile.WriteError("Echec de la suppresion du répertoire : " + e.Message);
                            break;
                        }
                        else
                            Console.WriteLine("Copie Ok");
                    }
            }
            catch (Exception e)
            {
                LogToFile.WriteError("Erreur de copie de répertoire : " + e.Message);
            }
            impersonator.UndoImpersonateUser();
        }

    }
}
